<template>
  <div class="min-h-screen flex flex-col bg-gradient-to-br from-blue-900 via-indigo-900 to-purple-900 text-gray-100">
    <!-- Animated background elements -->
    <div class="fixed inset-0 overflow-hidden pointer-events-none">
      <div class="absolute top-0 left-0 w-full h-full bg-grid opacity-20"></div>
      <div class="absolute top-0 left-0 w-full h-full bg-stars opacity-30"></div>
    </div>

    <header class="bg-gray-900/70 backdrop-blur-md p-4 shadow-lg border-b border-blue-500/20 z-10">
      <div class="container mx-auto flex justify-between items-center">
        <h1 class="text-3xl font-bold flex items-center tracking-wider">
          <i class="fa fa-cubes mr-3 text-blue-400 animate-pulse"></i>
          <span class="bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-purple-400">DistroboxFace</span>
        </h1>
        <div class="flex space-x-3">
          <button @click="refresh" class="bg-blue-500/20 hover:bg-blue-500/40 text-blue-300 px-4 py-2 rounded-md transition-all duration-300 transform hover:scale-105 flex items-center">
            <i class="fa fa-refresh mr-1"></i>
            <span>{{ text.refresh }}</span>
          </button>
          <button @click="openCreateModal" class="bg-green-500/20 hover:bg-green-500/40 text-green-300 px-4 py-2 rounded-md transition-all duration-300 transform hover:scale-105 flex items-center">
            <i class="fa fa-plus mr-1"></i>
            <span>{{ text.newContainer }}</span>
          </button>
        </div>
      </div>
    </header>

    <main class="flex-grow container mx-auto p-6 grid grid-cols-1 lg:grid-cols-3 gap-6 relative z-10">
      <!-- Containers List Panel -->
      <div class="lg:col-span-2 container-card bg-gray-900/50 backdrop-blur-sm rounded-xl shadow-lg overflow-hidden border border-blue-500/10 hover:border-blue-500/30 transition-all duration-300 transform hover:-translate-y-1 hover:shadow-blue-500/20 hover:shadow-xl">
        <div class="p-5 border-b border-gray-800 flex justify-between items-center">
          <h2 class="text-2xl font-semibold flex items-center">
            <i class="fa fa-server mr-2 text-blue-400"></i>
            <span>{{ text.installedContainers }}</span>
          </h2>
          <div class="relative max-w-xs" style="display: flex;">
            <input 
              v-model="state.searchQuery"
              type="text" 
              :placeholder="text.search" 
              class="bg-gray-800/70 text-gray-100 rounded-lg px-4 py-2 pl-10 focus:outline-none focus:ring-2 focus:ring-blue-500/50 w-full"
            >
            <i class="fa fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"
            style="margin-top: 5px;"></i>
          </div>
        </div>
        
        <div class="p-5">
          <div class="overflow-x-auto custom-scrollbar">
            <table class="min-w-full table-hover-effect">
              <thead>
                <tr class="bg-gray-800/50 text-left">
                  <th class="px-5 py-4 rounded-tl-lg text-gray-300 font-semibold">{{ text.name }}</th>
                  <th class="px-5 py-4 text-gray-300 font-semibold">{{ text.image }}</th>
                  <th class="px-5 py-4 text-gray-300 font-semibold">{{ text.status }}</th>
                  <th class="px-5 py-4 rounded-tr-lg text-right text-gray-300 font-semibold">{{ text.actions }}</th>
                </tr>
              </thead>
              <tbody>
                <tr 
                  v-for="container in filteredContainers" 
                  :key="container.name"
                  class="bg-gray-800/30 hover:bg-gray-700/30 transition-all duration-200 border-b border-gray-800"
                >
                  <td class="px-5 py-4 font-medium" @click="enterContainer(container.name)">{{ container.name }}</td>
                  <td class="px-5 py-4">{{ container.image }}</td>
                  <td class="px-5 py-4">
                    <span 
                      :class="`bg-${getStatusColor(container.status)}-500/20 text-${getStatusColor(container.status)}-400 px-3 py-1 rounded-full text-xs status-indicator`"
                    >
                      <span 
                        :class="`status-dot ${container.status === 'Running' ? 'running-dot' : 'stopped-dot'}`"
                      ></span>
                      {{ container.status }}
                    </span>
                  </td>
                  <td class="px-5 py-4 text-right">
                    <button 
                      v-if="container.status === 'Running'"
                      @click="enterContainer(container.name)"
                      class="btn-icon bg-blue-500/20 hover:bg-blue-500/40 text-blue-400 p-2 rounded mr-2 transition-all duration-200 hover:shadow-blue-500/30 hover:shadow"
                    >
                      <i class="fa fa-terminal"></i>
                    </button>
                    <button 
                      v-if="container.status === 'Running'"
                      @click="stopContainer(container.name)"
                      class="btn-icon bg-gray-500/20 hover:bg-gray-500/40 text-gray-400 p-2 rounded mr-2 transition-all duration-200 hover:shadow-gray-500/30 hover:shadow"
                    >
                      <i class="fa fa-pause"></i>
                    </button>
                    <button 
                      v-if="container.status !== 'Running'"
                      @click="startContainer(container.name)"
                      class="btn-icon bg-blue-500/20 hover:bg-blue-500/40 text-blue-400 p-2 rounded mr-2 transition-all duration-200 hover:shadow-blue-500/30 hover:shadow"
                    >
                      <i class="fa fa-play"></i>
                    </button>
                    <button 
                      @click="removeContainer(container.name)"
                      class="btn-icon bg-red-500/20 hover:bg-red-500/40 text-red-400 p-2 rounded transition-all duration-200 hover:shadow-red-500/30 hover:shadow"
                    >
                      <i class="fa fa-trash"></i>
                    </button>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>

      <!-- Available Images Panel -->
      <div style="margin-top: 50px;" class="container-card bg-gray-900/50 backdrop-blur-sm rounded-xl shadow-lg overflow-hidden border border-blue-500/10 hover:border-blue-500/30 transition-all duration-300 transform hover:-translate-y-1 hover:shadow-blue-500/20 hover:shadow-xl">
        <div class="p-5 border-b border-gray-800 flex justify-between items-center">
          <h2 class="text-2xl font-semibold flex items-center">
            <i class="fa fa-download mr-2 text-blue-400"></i>
            <span>{{ text.availableImages }}</span>
          </h2>
          <div class="relative max-w-xs" style="display: flex;">
            <input 
              v-model="state.imageSearchQuery"
              type="text" 
              :placeholder="text.searchImages" 
              class="bg-gray-800/70 text-gray-100 rounded-lg px-4 py-2 pl-10 focus:outline-none focus:ring-2 focus:ring-blue-500/50 w-full"
              @input="searchImages"
            >
            <i class="fa fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"
            style="margin-top: 5px;"></i>
          </div>
        </div>

        <div class="p-5 max-h-[600px] overflow-y-auto custom-scrollbar space-y-4">
          <div v-if="state.loadingImages" class="flex justify-center items-center py-8">
            <div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-400"></div>
          </div>
          <div v-else-if="state.errorImages" class="text-red-400 text-center py-4">
            {{ state.errorImages }}
          </div>
          <div v-else-if="filteredImages.length === 0" class="text-gray-400 text-center py-4">
            {{ text.noImagesFound }}
          </div>
          <div 
            v-else
            v-for="image in filteredImages" 
            :key="image.name"
            class="container-card bg-gray-800/30 rounded-xl p-4 hover:bg-gray-700/30 transition-all duration-200 cursor-pointer border border-gray-700/50 hover:border-blue-500/30 transform hover:-translate-y-1 hover:shadow-blue-500/20"
          >
            <div class="flex justify-between items-center">
              <h3 class="font-medium text-lg">{{ image.name }}</h3>
              <button 
                @click="createNewContainer(image.name)" 
                class="btn-icon bg-green-500/20 hover:bg-green-500/40 text-green-400 p-2 rounded transition-all duration-200 hover:shadow-green-500/30 hover:shadow"
              >
                <i class="fa fa-plus"></i>
              </button>
            </div>
            <p class="text-sm text-gray-400 mt-2">{{ image.description }}</p>
            <div class="mt-3 flex justify-between text-xs text-gray-500">
              <span>Size: {{ image.size }}</span>
              <span>Updated: {{ image.updated }}</span>
            </div>
          </div>
        </div>
      </div>
    </main>

    <footer class="bg-gray-900/70 backdrop-blur-md p-4 text-center text-gray-400 border-t border-blue-500/20">
      <p>DistroboxFace - A modern visual manager for distrobox containers</p>
    </footer>

    <!-- 新建容器模态框 -->
    <div v-if="showCreateModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50">
      <div class="bg-gray-900/90 rounded-xl p-6 w-full max-w-md border border-blue-500/20 shadow-2xl">
        <h3 class="text-xl font-semibold mb-4 text-blue-400">{{ text.newContainer }}</h3>
        <div class="space-y-4">
          <div>
            <label class="block text-sm font-medium text-gray-300 mb-1">{{ text.name }}</label>
            <input 
              v-model="newContainerName"
              type="text"
              class="w-full bg-gray-800/70 text-gray-100 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500/50"
              :placeholder="text.name"
            >
          </div>
          <div>
            <label class="block text-sm font-medium text-gray-300 mb-1">{{ text.image }}</label>
            <input 
              v-model="newContainerImage"
              type="text"
              class="w-full bg-gray-800/70 text-gray-100 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500/50"
              :placeholder="text.image"
            >
          </div>
          <div class="flex justify-end space-x-3 mt-6">
            <button 
              @click="showCreateModal = false"
              class="px-4 py-2 bg-gray-700/50 hover:bg-gray-700/70 text-gray-300 rounded-lg transition-all duration-200"
            >
              {{ text.cancel }}
            </button>
            <button 
              @click="handleCreateContainer"
              class="px-4 py-2 bg-blue-500/20 hover:bg-blue-500/40 text-blue-300 rounded-lg transition-all duration-200"
              :disabled="!newContainerImage"
            >
              {{ text.create }}
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, computed } from 'vue';
import type { Container, Image, AppState, Text } from './types';
import * as api from './utils/api';

// 状态管理
const state = ref<AppState>({
    containers: [],
    images: [],
    loading: false,
    loadingImages: false,
    error: null,
    errorImages: null,
    searchQuery: '',
    imageSearchQuery: ''
});

// 模态框状态
const showCreateModal = ref(false);
const newContainerName = ref('');
const newContainerImage = ref('');

// 国际化文本
const text: Text = {
    refresh: '刷新',
    newContainer: '新建容器',
    installedContainers: '已安装容器',
    availableImages: '可用镜像',
    name: '名称',
    image: '镜像',
    status: '状态',
    actions: '操作',
    search: '搜索容器...',
    create: '创建',
    delete: '删除',
    start: '启动',
    stop: '停止',
    enter: '进入',
    error: '错误',
    success: '成功',
    searchImages: '搜索镜像...',
    noImagesFound: '未找到匹配的镜像',
    cancel: '取消'
};

// 计算属性
const filteredContainers = computed(() => {
    if (!state.value.searchQuery) {
        return state.value.containers;
    }
    const query = state.value.searchQuery.toLowerCase();
    return state.value.containers.filter(container => 
        container.name.toLowerCase().includes(query) ||
        container.image.toLowerCase().includes(query)
    );
});

const filteredImages = computed(() => {
    return state.value.images;
});

// 方法
const getStatusColor = (status: string) => {
    switch (status) {
        case 'Running':
            return 'green';
        case 'Stopped':
            return 'red';
        case 'Paused':
            return 'yellow';
        default:
            return 'gray';
    }
};

const refresh = async () => {
    try {
        state.value.loading = true;
        state.value.error = null;
        state.value.containers = await api.listContainers();
    } catch (error) {
        state.value.error = error instanceof Error ? error.message : '刷新失败';
    } finally {
        state.value.loading = false;
    }
};

const createNewContainer = async (image: string) => {
    try {
        state.value.loading = true;
        state.value.error = null;
        await api.createContainer(image);
        await refresh();
    } catch (error) {
        state.value.error = error instanceof Error ? error.message : '创建容器失败';
    } finally {
        state.value.loading = false;
    }
};

const removeContainer = async (name: string) => {
    if (!confirm(`确定要删除容器 ${name} 吗？`)) {
        return;
    }
    
    try {
        state.value.loading = true;
        state.value.error = null;
        await api.removeContainer(name);
        await refresh();
    } catch (error) {
        state.value.error = error instanceof Error ? error.message : '删除容器失败';
    } finally {
        state.value.loading = false;
    }
};

const startContainer = async (name: string) => {
    try {
        state.value.loading = true;
        state.value.error = null;
        await api.startContainer(name);
        await refresh();
    } catch (error) {
        state.value.error = error instanceof Error ? error.message : '启动容器失败';
    } finally {
        state.value.loading = false;
    }
};

const stopContainer = async (name: string) => {
    try {
        state.value.loading = true;
        state.value.error = null;
        await api.stopContainer(name);
        await refresh();
    } catch (error) {
        state.value.error = error instanceof Error ? error.message : '停止容器失败';
    } finally {
        state.value.loading = false;
    }
};

const enterContainer = async (name: string) => {
    try {
        state.value.loading = true;
        state.value.error = null;
        await api.enterContainer(name);
    } catch (error) {
        state.value.error = error instanceof Error ? error.message : '进入容器失败';
    } finally {
        state.value.loading = false;
    }
};

// 搜索镜像方法
const searchImages = async () => {
    if (!state.value.imageSearchQuery) {
        state.value.images = [];
        return;
    }

    try {
        state.value.loadingImages = true;
        state.value.errorImages = null;
        const results = await api.searchImages(state.value.imageSearchQuery);
        state.value.images = results;
    } catch (error) {
        state.value.errorImages = error instanceof Error ? error.message : '搜索镜像失败';
    } finally {
        state.value.loadingImages = false;
    }
};

// 修改新建容器按钮的点击事件
const openCreateModal = () => {
    showCreateModal.value = true;
    newContainerName.value = '';
    newContainerImage.value = '';
};

// 处理创建容器
const handleCreateContainer = async () => {
    if (!newContainerImage.value) {
        state.value.error = '请输入镜像名称';
        return;
    }

    try {
        state.value.loading = true;
        state.value.error = null;
        await api.createContainer(newContainerImage.value, newContainerName.value || undefined);
        showCreateModal.value = false;
        await refresh();
    } catch (error) {
        state.value.error = error instanceof Error ? error.message : '创建容器失败';
    } finally {
        state.value.loading = false;
    }
};

// 生命周期钩子
onMounted(async () => {
    await refresh();
});
</script>

<style scoped>
/* Custom animations */
@keyframes float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-10px); }
}

@keyframes pulse-glow {
  0%, 100% { box-shadow: 0 0 5px rgba(75, 192, 192, 0.3); }
  50% { box-shadow: 0 0 15px rgba(75, 192, 192, 0.6); }
}

/* Custom utility classes */
.bg-grid {
  background-image: url('');
}

.bg-stars {
  background-image: url('');
}

.animate-float {
  animation: float 6s ease-in-out infinite;
}

.animate-pulse-glow {
  animation: pulse-glow 2s ease-in-out infinite;
}

/* Custom component styles */
.container-card {
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
  margin-bottom: 20px;
}

.container-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(139, 92, 246, 0.1), transparent);
  transition: all 0.6s ease;
}

.container-card:hover::before {
  left: 100%;
}

.status-indicator {
  display: flex;
  align-items: center;
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 6px;
}

.running-dot {
  background-color: #22c55e;
  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

.stopped-dot {
  background-color: #eab308;
}
/* 表格最小宽度控制 */
.min-w-full {
  min-width: 100%;
}

.table-hover-effect tr {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
}

.table-hover-effect tr:hover {
  /* transform: translateX(1px); */
  background: linear-gradient(90deg, rgba(100, 108, 255, 0.1), rgba(100, 108, 255, 0.05));
  box-shadow: -2px 0 0 rgba(100, 108, 255, 0.5), 
              0 1px 2px rgba(0, 0, 0, 0.1);
}
/* 表格行选中状态 */
.table-hover-effect tbody tr.selected {
  background: linear-gradient(90deg, rgba(100, 108, 255, 0.2), rgba(100, 108, 255, 0.1));
  transform: translateX(2px);
  box-shadow: -2px 0 0 rgba(100, 108, 255, 0.8);
}
/* 表格行动画延迟，创建波浪效果 */
.table-hover-effect tbody tr:nth-child(1) { transition-delay: 0ms; }
.table-hover-effect tbody tr:nth-child(2) { transition-delay: 50ms; }
.table-hover-effect tbody tr:nth-child(3) { transition-delay: 100ms; }
.table-hover-effect tbody tr:nth-child(4) { transition-delay: 150ms; }
.table-hover-effect tbody tr:nth-child(5) { transition-delay: 200ms; }

.table-hover-effect tr td {
  padding-left: 12px;
}

/* 响应式表格调整 */
@media (max-width: 768px) {
  .min-w-full {
    min-width: 640px; /* 在小屏幕上设置更大的最小宽度，强制出现滚动条 */
  }

}
/* 间距类 */
.px-5 { padding-left: 1.25rem; padding-right: 1.25rem; }
.py-4 { padding-top: 1rem; padding-bottom: 1rem; }
.p-2 { padding: 0.5rem; }
.mr-2 { margin-right: 0.5rem; }

/* 文本对齐 */
.text-right { text-align: right; }
.text-center { text-align: center; }
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 0.5rem;
  transition: all 0.2s ease;
  position: relative;
  overflow: hidden;
  background-color: rgba(59, 130, 246, 0.2);
  color: #93c5fd;
}

.btn-icon:hover {
  background-color: rgba(59, 130, 246, 0.4);
  box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
  transform: translateY(-1px);
}
.btn-icon:active {
  transform: translateY(0);
  box-shadow: 0 2px 6px rgba(59, 130, 246, 0.3);
}

.btn-icon:hover i {
  transform: scale(1.1);
}

/* 按钮背景动效 */
.btn-icon::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
  transition: all 0.6s ease;
}

.btn-icon:hover::before {
  left: 100%;
}


.text-blue-400 { color: #93c5fd; }

/* 响应式调整 */
@media (max-width: 768px) {
  .px-5 { padding-left: 1rem; padding-right: 1rem; }
  .py-4 { padding-top: 0.75rem; padding-bottom: 0.75rem; }
}
/* 基础溢出控制 */
.overflow-x-auto {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch; /* 增强移动设备滚动体验 */
}
/* 滚动条美化（保留原自定义样式并增强） */
.custom-scrollbar {
  scrollbar-width: thin;
  scrollbar-color: rgba(100, 108, 255, 0.5) rgba(31, 41, 55, 0.2);
}

/* Scrollbar styles */
.custom-scrollbar::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

.custom-scrollbar::-webkit-scrollbar-track {
  background: rgba(156, 163, 175, 0.1);
  border-radius: 10px;
}

.custom-scrollbar::-webkit-scrollbar-thumb {
  background: rgba(156, 163, 175, 0.3);
  border-radius: 10px;
}

.custom-scrollbar::-webkit-scrollbar-thumb:hover {
  background: rgba(156, 163, 175, 0.5);
}
/* 基础布局样式 */
.min-h-screen { min-height: 100vh; }
.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.w-full { width: 100%; }
.p-4 { padding: 1rem; }
.p-5 { padding: 1.25rem; }
.p-6 { padding: 1.5rem; }
.mx-auto { margin-left: auto; margin-right: auto; }
.space-x-3 > * + * { margin-left: 0.75rem; }

/* 颜色与背景 */
.bg-gradient-to-br {
  background: linear-gradient(135deg, #2890cc, #224fe6, #780fa1);
}
.bg-gray-900\/70 { background: rgba(31, 41, 55, 0.7); }
.bg-gray-800\/70 { background: rgba(31, 41, 55, 0.7); }
.bg-gray-800\/50 { background: rgba(31, 41, 55, 0.5); }
.bg-gray-800\/30 { background: rgba(31, 41, 55, 0.3); }
.bg-blue-500\/20 { background: rgba(59, 130, 246, 0.2); }
.text-gray-100 { color: #f3f4f6; }
.text-blue-400 { color: #646cff; }
.text-transparent { color: transparent; }
.bg-clip-text { background-clip: text; }

/* 卡片与容器样式 */
.container-card {
  background: rgba(31, 41, 55, 0.4);
  border-radius: 1.5rem;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);
  backdrop-filter: blur(12px);
  position: relative;
  overflow: hidden;
}

/* 标题与文本样式 */
.text-3xl { font-size: 1.875rem; line-height: 2.25rem; }
.text-2xl { font-size: 1.5rem; line-height: 2rem; }
.font-bold { font-weight: 700; }
.tracking-wider { letter-spacing: 0.05em; }

/* 按钮样式 */
.button {
  padding: 0.5rem 1rem;
  border-radius: 0.75rem;
  transition: transform 0.3s ease, box-shadow 0.3s ease;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.button:hover {
  transform: scale(1.05);
  box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
}

.btn-icon {
  padding: 0.5rem;
  border-radius: 0.625rem;
}

/* 输入框样式 */
.input {
  padding: 0.75rem 1.25rem;
  padding-left: 3rem;
  border-radius: 1rem;
  background: rgba(31, 41, 55, 0.7);
  color: #e5e7eb;
  border: 2px solid transparent;
  font-size: 0.875rem;
}

.input:focus {
  border-color: #646cff;
  outline: none;
  box-shadow: 0 0 0 3px rgba(100, 108, 255, 0.3);
}

/* 表格样式 */
.table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 1.25rem;
}

.table th,
.table td {
  padding: 1rem;
  text-align: left;
}

.table-hover-effect tbody tr {
  transition: transform 0.2s ease;
}

.table-hover-effect tbody tr:hover {
  /* transform: translateX(8px); */
  background: rgba(59, 130, 246, 0.1);
}

/* 状态指示器 */
.status-indicator {
  font-size: 0.75rem;
  align-items: center;
  gap: 0.5rem;
}

.status-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  display: block;
}

.running-dot {
  background-color: #22c55e;
  box-shadow: 0 0 8px rgba(34, 197, 94, 0.3);
  animation: pulse-green 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

.stopped-dot {
  background-color: #f59e0b;
  box-shadow: 0 0 8px rgba(245, 158, 11, 0.3);
}

/* 动画增强 */
.animate-pulse {
  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.7; }
}

@keyframes pulse-green {
  0% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.4); }
  70% { box-shadow: 0 0 0 10px rgba(34, 197, 94, 0); }
  100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0); }
}

/* 滚动条样式 */
.custom-scrollbar {
  scrollbar-width: thin;
  scrollbar-color: #646cff rgba(31, 41, 55, 0.5);
}

.custom-scrollbar::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

.custom-scrollbar::-webkit-scrollbar-track {
  background: rgba(31, 41, 55, 0.3);
  border-radius: 3px;
}

.custom-scrollbar::-webkit-scrollbar-thumb {
  background: #646cff;
  border-radius: 3px;
}

/* 响应式断点 */
@media (min-width: 1024px) {
  .lg\:grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
  .lg\:col-span-2 { grid-column: span 2; }
}

/* 新增未来感元素 */
.header-glow {
  box-shadow: 0 0 24px rgba(59, 130, 246, 0.2);
  backdrop-filter: blur(16px);
}

.card-glow:hover {
  box-shadow: 0 8px 24px rgba(59, 130, 246, 0.3);
  transform: translateY(-4px);
}

.gradient-text {
  background: linear-gradient(45deg, #646cff, #a855f7);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* 原代码补充样式 */
.bg-grid {
  background-image: url('');
}

.bg-stars {
  background-image: url('');
}

.animate-float {
  animation: float 6s ease-in-out infinite;
}

@keyframes float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-10px); }
}

.animate-pulse-glow {
  animation: pulse-glow 2s ease-in-out infinite;
}

@keyframes pulse-glow {
  0%, 100% { box-shadow: 0 0 5px rgba(75, 192, 192, 0.3); }
  50% { box-shadow: 0 0 15px rgba(75, 192, 192, 0.6); }
}

.container-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(90, 24, 154, 0.1), transparent);
  transition: all 0.6s ease;
}

.container-card:hover::before {
  left: 100%;
}


/* 按钮状态颜色 */
.bg-blue-500\/20 { background: rgba(59, 130, 246, 0.2); }
.bg-green-500\/20 { background: rgba(34, 197, 94, 0.2); }
.bg-red-500\/20 { background: rgba(244, 67, 54, 0.2); }
.bg-gray-500\/20 { background: rgba(107, 114, 128, 0.2); }

.text-blue-300 { color: #90cdf4; }
.text-green-300 { color: #86efac; }
.text-red-400 { color: #f87171; }
.text-gray-400 { color: #9ca3af; }

/* 阴影增强 */
.shadow-lg { box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1); }
.shadow-blue-500\/20 { box-shadow: 0 4px 6px rgba(59, 130, 246, 0.2); }
.left-3 { margin-left: 0.75rem; }
.text-gray-400 { color: #9ca3af; } /* 对应Tailwind的gray-400 */

/* 搜索图标容器整体样式（结合输入框结构） */
.input-group {
  position: relative;
  display: flex;
  align-items: center;
}

.input-group i {
  /* 图标基础样式 */
  font-size: 1.125rem; /* 18px */
  pointer-events: none; /* 避免干扰输入交互 */
  transition: color 0.3s ease; /* 颜色过渡效果 */
  
  /* 组合定位类 */
  @apply absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400;
}

/* 输入框聚焦时图标颜色变化 */
.input:focus ~ .input-group i {
  color: #646cff; /* 蓝色高亮 */
}

/* 响应式调整（小屏幕图标位置微调） */
@media (max-width: 640px) {
  .input-group i {
    left: 1rem; /* 16px */
    font-size: 1rem; /* 16px */
  }
}
</style>  